package com.ljkj.cordial.chat.util;

import android.support.annotation.NonNull;

import com.lanjiu.lib.imclient.user.UserPreferences;
import com.lanjiu.lib.utils.file.FileOperator;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;

import javax.annotation.Nullable;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;

/**
 * @description:
 * @author: Panwei
 * @date: 2020/3/7 14:46
 */
public class Http {

    public interface URL {
        String DOMAIN = "http://192.168.1.6:8080/";

        String UPLOAD_AVATAR = DOMAIN + "upload/";
    }

    public static final int REQUEST_SUCCESS = 200;
    public static final int REQUEST_FAILURE = 500;

    private static final String RESPONSE_KEY_CODE = "code";
    private static final String RESPONSE_KEY_MSG = "msg";
    private static final String RESPONSE_KEY_DATA = "data";

    private Http() {
    }

    public static void uploadAvatar(String path, RequestCallback callback) {
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("avatar", FileOperator.getFileName(path, true), RequestBody.create(MediaType.parse("multipart/form-data"), new File(path)))
                .addFormDataPart("uid", UserPreferences.getUserId())
                .build();
        FileRequestBody fileRequestBody = new FileRequestBody(requestBody, callback);
        Request request = new Request.Builder()
                .url(URL.UPLOAD_AVATAR)
                .post(fileRequestBody)
                .build();
        client.newCall(request).enqueue(new OkHttpCallback(callback));
    }

    /**
     * 文件上传进度条
     */
    private static class FileRequestBody extends RequestBody {
        private RequestBody mRequestBody;
        private RequestCallback mRequestCallback;
        private long mContentLength;

        public FileRequestBody(RequestBody requestBody, RequestCallback callback) {
            this.mRequestBody = requestBody;
            this.mRequestCallback = callback;
        }

        @Override
        public long contentLength() {
            try {
                if (mContentLength == 0)
                    mContentLength = mRequestBody.contentLength();
                return mContentLength;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return -1;
        }

        @Nullable
        @Override
        public MediaType contentType() {
            return mRequestBody.contentType();
        }

        @Override
        public void writeTo(@NonNull BufferedSink sink) throws IOException {
            ByteSink byteSink = new ByteSink(sink);
            BufferedSink mBufferedSink = Okio.buffer(byteSink);
            mRequestBody.writeTo(mBufferedSink);
            mBufferedSink.flush();
        }

        private final class ByteSink extends ForwardingSink {
            //已经上传的长度
            private long mByteLength = 0L;

            ByteSink(Sink delegate) {
                super(delegate);
            }

            @Override
            public void write(@NonNull Buffer source, long byteCount) throws IOException {
                super.write(source, byteCount);
                mByteLength += byteCount;
                double f1 = new BigDecimal((float) mByteLength / contentLength()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                int progress = (int) (f1 * 100);
                mRequestCallback.onProgress(progress);
            }
        }
    }

    /**
     * 统一的回调处理
     */
    private static class OkHttpCallback implements Callback {

        private RequestCallback mRequestCallback;

        public OkHttpCallback(RequestCallback callback) {
            this.mRequestCallback = callback;
        }

        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) {
            if (mRequestCallback != null)
                mRequestCallback.onFailure("请求失败，请稍后重试");
        }

        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
            if (mRequestCallback != null && response.body() != null) {
                String json = response.body().string();
                int code = JsonKit.optCode(json);
                if (code == REQUEST_SUCCESS)
                    mRequestCallback.onResponse(code, JsonKit.optData(json));
                else
                    mRequestCallback.onFailure(JsonKit.optMsg(json));
            }
        }
    }

    /**
     * 考虑到今后换库的风险，使用自己定义的回调处理
     */
    public interface RequestCallback {

        default void onProgress(int progress) {
        }

        default void onFailure(String msg) {
        }

        void onResponse(int code, String data);
    }

    /**
     * Json 工具包装
     */
    private static class JsonKit {
        private static int optCode(String json) {
            try {
                JSONObject jsonObj = new JSONObject(json);
                return jsonObj.optInt(RESPONSE_KEY_CODE);
            } catch (JSONException e) {
                return REQUEST_FAILURE;
            }
        }

        private static String optMsg(String json) {
            try {
                JSONObject jsonObj = new JSONObject(json);
                return jsonObj.optString(RESPONSE_KEY_MSG);
            } catch (JSONException e) {
                return "请求失败，请稍后重试";
            }
        }

        private static String optData(String json) {
            try {
                JSONObject jsonObj = new JSONObject(json);
                return jsonObj.optString(RESPONSE_KEY_DATA);
            } catch (JSONException e) {
                return null;
            }
        }
    }
}
